package com.example.commen.net.easyHttp

import android.util.Log
import androidx.lifecycle.LifecycleOwner
import com.alibaba.fastjson.JSON
import com.blankj.utilcode.util.LogUtils
import com.example.commen.AppExecutors
import com.example.commen.R
import com.example.commen.base.UCApplication
import com.example.commen.net.easyHttp.model.HttpData
import com.google.gson.JsonElement
import com.hjq.http.EasyHttp
import com.hjq.http.body.JsonBody
import com.hjq.http.config.IRequestApi
import com.hjq.http.exception.FileMD5Exception
import com.hjq.http.exception.ServerException
import com.hjq.http.exception.TimeoutException
import com.hjq.http.listener.HttpCallback
import com.hjq.http.listener.OnDownloadListener
import com.hjq.http.model.HttpMethod
import com.hjq.http.model.ResponseClass
import com.hjq.toast.Toaster
import com.wx.android.common.util.ThreadUtils
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import java.io.File
import java.io.Serializable

class EasyHttpManager {


    companion object {
        private var instance: EasyHttpManager? = null

        @Synchronized
        @JvmStatic
        fun get(): EasyHttpManager {
            if (instance == null) {
                instance = EasyHttpManager()
            }
            return instance as EasyHttpManager
        }
    }


    fun get(context: LifecycleOwner, api: IRequestApi, listener: HttpCallback<*>) {
        try {
            EasyHttp.get(context)
                .api(api)
                .request(listener)
        } catch (e: Exception) {
            LogUtils.e("网络请求错误:", e.message)
        }
    }

    fun get(context: LifecycleOwner, api: IRequestApi, json: String, listener: HttpCallback<*>) {
        try {
            EasyHttp.get(context)
                .api(api)
                .request(listener)
        } catch (e: Exception) {
            LogUtils.e("网络请求错误:", e.message)
        }
    }

    fun get(context: LifecycleOwner, api: String, listener: HttpCallback<*>) {
        try {
            EasyHttp.get(context)
                .api(api)
                .request(listener)
        } catch (e: Exception) {
            LogUtils.e("网络请求错误:", e.message)
        }
    }

    fun put(context: LifecycleOwner, api: IRequestApi, listener: HttpCallback<*>) {
        try {
            EasyHttp.put(context)
                .api(api)
                .request(listener)
        } catch (e: Exception) {
            LogUtils.e("网络请求错误:", e.message)
        }
    }

    fun put(context: LifecycleOwner, api: IRequestApi, json: String, listener: HttpCallback<*>) {
        try {
            EasyHttp.put(context)
                .api(api)
                .body(JsonBody(json))
                .request(listener)
        } catch (e: Exception) {
            LogUtils.e("网络请求错误:", e.message)
        }
    }

    fun delete(context: LifecycleOwner, api: IRequestApi, listener: HttpCallback<*>) {
        try {
            EasyHttp.delete(context)
                .api(api)
                .request(listener)
        } catch (e: Exception) {
            LogUtils.e("网络请求错误:", e.message)
        }
    }

    fun post(context: LifecycleOwner, api: IRequestApi, listener: HttpCallback<*>) {
        try {
            EasyHttp.post(context)
                .api(api)
                .request(listener)
        } catch (e: Exception) {
            LogUtils.e("网络请求错误:", e.message)
        }
    }

    fun post(context: LifecycleOwner, api: IRequestApi, json: String, listener: HttpCallback<*>) {
        EasyHttp.post(context)
            .api(api)
            .body(JsonBody(json))
            .request(listener)
    }

    fun post(context: LifecycleOwner, api: String, listener: HttpCallback<*>) {
        EasyHttp.post(context)
            .api(api)
            .request(listener)
    }

    fun post(context: LifecycleOwner, api: String, json: String, listener: HttpCallback<*>) {
        EasyHttp.post(context)
            .api(api)
            .body(JsonBody(json))
            .request(listener)
    }

    fun download(
        context: LifecycleOwner,
        savePath: File,
        url: String,
        listener: HttpCallback<*>
    ) {
        EasyHttp.download(context)
            .method(HttpMethod.GET)
            .file(savePath) //.url("https://qd.myapp.com/myapp/qqteam/AndroidQQ/mobileqq_android.apk")
            .url(url)
//                .md5("b05b25d4738ea31091dd9f80f4416469")
            .listener(object : OnDownloadListener {
                override fun onStart(file: File) {
                }

                override fun onProgress(file: File, progress: Int) {
                }

                override fun onComplete(file: File) {
                    LogUtils.d("下载完成：" + file.path)
                }

                override fun onError(file: File, e: java.lang.Exception) {
                    LogUtils.d(e.message)
                    if (e is FileMD5Exception) {
                        // 如果是文件 md5 校验失败，则删除文件
                        file.delete()
                    }
                }

                override fun onEnd(file: File) {
                }
            })
            .start()
    }

    /**
     * 废弃,不好用
     */
    fun Upload(context: LifecycleOwner, api: IRequestApi, listener: HttpCallback<*>) {
        EasyHttp.post(context)
            .api(api)
            .request(listener)
    }

    fun upLoadFiles(
        url: String,
        filesPath: List<File>,
        token: String,
        listener: HttpCallback<List<UpLoadFileResult.Data>>
    ) {

        try {
            if (filesPath.isNotEmpty()) {
                ThreadUtils.execute {
                    try {
                        val mediaType =
                            MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
                        val multipartBody = MultipartBody.Builder().setType(MultipartBody.FORM)
                        filesPath.forEach {
                            // 创建RequestBody对象
                            val requestBody = RequestBody.create(mediaType, it)
                            // 创建MultipartBody对象
                            multipartBody.addFormDataPart("file", it.name, requestBody)
                        }
                        val request: Request = Request.Builder()
                            .url(url)
                            .post(multipartBody.build())
                            .header("token", token)
                            .build()
                        val client = OkHttpClient()
                        client.newCall(request).execute().use { response ->
                            val result: String = response.body()!!.string()
                            val data = JSON.parseObject(result, UpLoadFileResult::class.java)
                            LogUtils.i(result)
                            Log.i("snd", "上传: " + result)
                            UCApplication.getCurrentActivity().runOnUiThread {
                                if (data != null) {
                                    if (response.isSuccessful() && data.isRequestSucceed) {
                                        listener.onSucceed(data.data)
                                    } else {
                                        listener.onFail(Exception(data.message!!))
                                    }
                                } else {
                                    listener.onFail(Exception("数据错误,请稍后再试"))
                                }
                            }
                        }

                    } catch (e: Exception) {
                        listener.onFail(e)
                        e.printStackTrace()
                    }
                }
            } else {
                listener.onSucceed(listOf())
                LogUtils.e("未上传文件")
            }
        } catch (e: Exception) {
            listener.onFail(e)
        }

    }


    fun uploadfile(
        url: String,
        filePath: File,
        token: String,
        listener: HttpCallback<List<UpLoadFileResult.Data>>
    ) {
        upLoadFiles(url, arrayListOf(filePath), token, listener)
    }

    class UpLoadFileResult : HttpData<List<UpLoadFileResult.Data>>(), Serializable {
        data class Data(
            var fimeName: String = "",
            var base: String = "",
            var downUrl: String = "",
            var picURL: String = ""
        ) : Serializable
    }


    fun postHttpData(context: LifecycleOwner, url: String, json: String): HttpData<JsonElement?>? {
        return try {
            EasyHttp.post(context)
                .api { url }
                .body(JsonBody(json))
                .execute(object : ResponseClass<HttpData<JsonElement?>>() {})
        } catch (e: Exception) {
            handleError(e)
            null
        }
    }

    fun getHttpData(context: LifecycleOwner, url: String): HttpData<JsonElement?>? {
        return try {
            EasyHttp
                .get(context)
                .api { url }
                .execute(object : ResponseClass<HttpData<JsonElement?>>() {})
        } catch (e: Exception) {
            handleError(e)
            null
        }
    }

    fun putHttpData(context: LifecycleOwner, url: String, json: String): HttpData<JsonElement?>? {
        return try {
            EasyHttp.put(context)
                .api { url }
                .body(JsonBody(json))
                .execute(object : ResponseClass<HttpData<JsonElement?>>() {})
        } catch (e: Exception) {
            handleError(e)
            null
        }
    }

    fun putHttpData(context: LifecycleOwner, url: String): HttpData<JsonElement?>? {
        return try {
            EasyHttp
                .put(context)
                .api { url }
                .execute(object : ResponseClass<HttpData<JsonElement?>>() {})
        } catch (e: Exception) {
            handleError(e)
            null
        }
    }


    /**
     * 异常捕获
     */
    private fun handleError(e: Exception?) {
        LogUtils.e("EasyHttpManager", "handleError:${e?.message}")
        when (e) {
            is TimeoutException -> {
                AppExecutors.getInstance().mainThread().execute {
                    Toaster.show(
                        UCApplication.getBaseApplication().getString(R.string.http_server_out_time)
                    )
                }
            }

            is ServerException -> {
                AppExecutors.getInstance().mainThread().execute {
                    Toaster.show(
                        UCApplication.getBaseApplication().getString(R.string.http_server_error)
                    )
                }
            }
        }
    }

}